home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 8 code / Curves in Quickdraw / QD Curves / Access.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-09  |  11.3 KB  |  472 lines  |  [TEXT/KAHL]

  1. #include <Memory.h>
  2. #include <ToolUtils.h>
  3. #include <QuickDraw.h>
  4. #include <Fonts.h>
  5. #include <stdio.h>
  6. #include <FixMath.h>
  7. #include <Resources.h>
  8.  
  9. #include "sfnt.h"
  10. #include "Access.h"
  11.  
  12. /********************* Private functions *****************/
  13.  
  14. long PostFontError(long error)
  15. {
  16.     if (error)
  17.         Debugger();
  18. }
  19.  
  20. static short GetFontState(Handle sfnt)
  21. {
  22.     short state;
  23.  
  24.     LoadResource(sfnt);
  25.     state = HGetState(sfnt);
  26.     HNoPurge(sfnt);
  27.     return state;
  28. }
  29.  
  30. static void SetFontState(Handle sfnt, short state)
  31. {
  32.     HSetState(sfnt, state);
  33. }
  34.  
  35. /*    Macro and glue routine to make handle growing easier.
  36. */
  37. #define SHS(h, s)    NiceSetHandleSize((Handle)h, s)
  38.  
  39. static short NiceSetHandleSize(Handle h, long size)
  40. {
  41.     SetHandleSize(h, size);
  42.     return MemError();
  43. }
  44.  
  45. /*    Some private calls to return pointers to various sfnt pieces.
  46. */
  47. static void* GetSfntTablePtr(Handle sfnt, fontTableTag tag)
  48. {
  49.     FontTableInfo info;
  50.  
  51.     if (GetSfntTableInfo(sfnt, tag, &info))
  52.         return 0;
  53.     return *sfnt + info.offset;
  54. }
  55.  
  56. static void* GetSfntGlyphPtr(Handle sfnt, long glyphIndex, long* length)
  57. {
  58.     void* loc;
  59.     char* glyphStart;
  60.     sfnt_FontHeader* head;
  61.  
  62.     if (!((head = GetSfntTablePtr(sfnt, tag_FontHeader)) &&
  63.         (loc = GetSfntTablePtr(sfnt, tag_IndexToLoc)) &&
  64.         (glyphStart = GetSfntTablePtr(sfnt, tag_GlyphData))))
  65.         return 0;
  66.  
  67.     if (head->indexToLocFormat == SHORT_INDEX_TO_LOC_FORMAT)
  68.     {    unsigned short* offset = (unsigned short*)loc + glyphIndex;
  69.         *length = (long)(offset[1] - *offset) << 1;
  70.         return glyphStart + ((long)*offset << 1);
  71.     }
  72.     else
  73.     {    long* offset = (long*)loc + glyphIndex;
  74.         *length = offset[1] - *offset;
  75.         return glyphStart + *offset;
  76.     }
  77. }
  78.  
  79. /********************** Public Font Tool Calls *******************/
  80.  
  81. long CountSfntTables(Handle sfnt)
  82. {
  83.     short state = GetFontState(sfnt);
  84.     short tables = ((sfnt_OffsetTable*)*sfnt)->numOffsets;
  85.     SetFontState(sfnt, state);
  86.     return tables;
  87. }
  88.  
  89. fontTableTag GetSfntTag(Handle sfnt, long index)
  90. {
  91.     fontTableTag tag = 0;
  92.     short state = GetFontState(sfnt);
  93.     if (index < ((sfnt_OffsetTable*)*sfnt)->numOffsets)
  94.         tag = ((sfnt_OffsetTable*)*sfnt)->table[index].tableTag;
  95.     SetFontState(sfnt, state);
  96.     return tag;
  97. }
  98.  
  99. FontError GetSfntTableInfo(Handle sfnt, fontTableTag tag, FontTableInfo* fTable)
  100. {
  101.     short state = GetFontState(sfnt);
  102.     register sfnt_OffsetTable* dir = (sfnt_OffsetTable*)*sfnt;
  103.     register sfnt_DirectoryEntry* table = dir->table;
  104.     register short count = dir->numOffsets;
  105.     FontError error = fNoError;
  106.  
  107.     for (; --count >= 0; table++)
  108.         if (table->tableTag == tag)
  109.         {    fTable->offset = table->offset;
  110.             fTable->length = table->length;
  111.             fTable->checkSum = table->checkSum;
  112.             break;
  113.         }
  114.     if (count < 0)
  115.         error = PostFontError(fTableNotFound);
  116.     SetFontState(sfnt, state);
  117.     return error;
  118. }
  119.  
  120. FontError GetSfntTable(Handle sfnt, fontTableTag tag, Handle userCopy)
  121. {
  122.     FontTableInfo info;
  123.     FontError error;
  124.  
  125.     if (error = GetSfntTableInfo(sfnt, tag, &info))
  126.         return error;
  127.  
  128.     SetHandleSize(userCopy, info.length);
  129.     if (MemError())
  130.         return PostFontError(fMemoryError);
  131.     
  132.     {    short state = GetFontState(sfnt);
  133.         BlockMove(*sfnt + info.offset, *userCopy, info.length);
  134.         SetFontState(sfnt, state);
  135.     }
  136.     return fNoError;
  137. }
  138.  
  139. FontError GetSfntNameString(Handle sfnt, long nameID, Str255 name)
  140. {
  141.     register sfnt_NamingTable* nameT;
  142.     register sfnt_NameRecord* nameR;
  143.     register short count;
  144.     short state = GetFontState(sfnt);
  145.  
  146.     if (!(nameT = GetSfntTablePtr(sfnt, tag_NamingTable)))
  147.     {    SetFontState(sfnt, state);
  148.         return fTableNotFound;
  149.     }
  150.  
  151.     nameR = (sfnt_NameRecord*)(nameT + 1);
  152.     count = nameT->count;
  153.  
  154.     /*    This section can be changed to get font names in other languages
  155.     */
  156.     for (; --count >= 0; nameR++)
  157.         if (nameR->platformID == plat_Macintosh &&
  158.             nameR->specificID == smRoman     &&
  159.             nameR->languageID == lang_English   &&
  160.             nameR->nameID == nameID)
  161.         {
  162.             name[0] = nameR->length <= 255 ? nameR->length : 255;
  163.             BlockMove((Ptr)nameT + nameT->stringOffset + nameR->offset, (Ptr)&name[1], name[0]);
  164.             SetFontState(sfnt, state);
  165.             return fNoError;
  166.         }
  167.  
  168.     name[0] = 0;
  169.     SetFontState(sfnt, state);
  170.     return fNameNotFound;
  171. }
  172.  
  173. /*    Returns the glyph index for the given character code, or
  174.  *    an error code.
  175.  */
  176. long GetCharGlyphIndex(Handle sfnt, unsigned short charCode)
  177. {
  178.     sfnt_char2IndexDirectory* table;
  179.     short i;
  180.     long mapOffset = 0;
  181.     long glyphIndex = 0;        /* missing character glyph */
  182.     short state = GetFontState(sfnt);
  183.  
  184.     if (!(table = GetSfntTablePtr(sfnt, tag_CharToIndexMap)))
  185.     {    SetFontState(sfnt, state);
  186.         return PostFontError(fTableNotFound);
  187.     }
  188.  
  189.     {    register sfnt_platformEntry* plat = table->platform;
  190.     
  191.         /* You can change this section to look for other scripts
  192.         */
  193.         for ( i = table->numTables - 1; i >= 0; --i )
  194.         {    if ( plat->platformID == plat_Macintosh && plat->specificID == smRoman)
  195.             {    mapOffset = plat->offset;
  196.                 break;
  197.             }
  198.             ++plat;
  199.         }
  200.     }
  201.     
  202.     if (mapOffset)
  203.     {    sfnt_mappingTable* mapping = (sfnt_mappingTable*)((char*)table + mapOffset);
  204.         
  205.         switch ( mapping->format ) {
  206.         case 0:
  207.             {    Byte* glyphs = (Byte*)(mapping + 1);
  208.                 glyphIndex = glyphs[charCode];
  209.             }
  210.             break;
  211.         case 6:
  212.             {    short* glyphs = (short*)(mapping + 1);
  213.                 short first = *glyphs++;
  214.                 short count = *glyphs++;
  215.                 charCode -= first;
  216.                 if (charCode < count)
  217.                     glyphIndex = glyphs[charCode];
  218.             }
  219.             break;
  220.         default:
  221.             glyphIndex = PostFontError(fUnimplemented);
  222.         }
  223.     }
  224.     else
  225.         glyphIndex = PostFontError(fCMapNotFound);
  226.  
  227.     SetFontState(sfnt, state);
  228.     return glyphIndex;
  229. }
  230.  
  231. long CountSfntGlyphs(Handle sfnt)
  232. {
  233.     sfnt_maxProfileTable* profile;
  234.     short glyphs;
  235.  
  236.     if (!(profile = GetSfntTablePtr(sfnt, tag_MaxProfile)))
  237.         return PostFontError(fTableNotFound);
  238.  
  239.     {    short state = GetFontState(sfnt);
  240.         glyphs = profile->numGlyphs;
  241.         SetFontState(sfnt, state);
  242.     }
  243.     return glyphs;
  244. }
  245.  
  246. #define GetUnsignedByte( p ) ((Byte)(*p++))
  247.  
  248. FontError GetGlyphOutline(Handle sfnt, long glyphIndex, GlyphOutline* gOutline, Matrix xform)
  249. {
  250.     short upem, state, sideBearing, adjustToLsb;
  251.     short* glyph;
  252.     sfnt_FontHeader* head;
  253.     sfnt_HorizontalHeader* hhea;
  254.     sfnt_HorizontalMetrics* hori;
  255.     long length;
  256.     FontError error = fNoError;
  257.  
  258.     state = GetFontState( sfnt );
  259.     HLock( sfnt );
  260.  
  261.     if (!((head = GetSfntTablePtr(sfnt, tag_FontHeader)) &&
  262.         (hhea = GetSfntTablePtr(sfnt, tag_HoriHeader)) &&
  263.         (hori = GetSfntTablePtr(sfnt, tag_HorizontalMetrics))))
  264.     {    error = fTableNotFound;
  265.         goto EXIT;
  266.     }
  267.  
  268.     upem = head->unitsPerEm;
  269.  
  270.     {    long longMetrics = hhea->numberLongMetrics;
  271.         if ( glyphIndex < longMetrics )
  272.         {    gOutline->advance.x = FixRatio( hori[glyphIndex].advance, upem );
  273.             sideBearing = hori[glyphIndex].sideBearing;
  274.         }
  275.         else
  276.         {    short *lsb = (short *)&hori[longMetrics]; /* first entry after[AW,LSB] array */
  277.             
  278.             gOutline->advance.x = FixRatio( hori[longMetrics-1].advance, upem );
  279.             sideBearing = hori[glyphIndex - longMetrics].sideBearing;
  280.         }
  281.         gOutline->advance.y = 0;
  282.     }
  283.  
  284.     gOutline->origin.x = gOutline->origin.y = 0;
  285.  
  286.     if (!(glyph = GetSfntGlyphPtr(sfnt, glyphIndex, &length)))
  287.     {    error = fGlyphNotFound;
  288.         goto EXIT;
  289.     }
  290.  
  291.     if (length == 0)
  292.     {    gOutline->contourCount = gOutline->pointCount = 0;
  293.         goto EXIT;
  294.     }
  295.  
  296.     gOutline->contourCount = *glyph++;
  297.     adjustToLsb = *glyph - sideBearing;        /* xmin - lsb */
  298.     glyph += 4;                        /* skip bounds rect */
  299.  
  300.     if (gOutline->contourCount == 0)
  301.         gOutline->pointCount = 0;
  302.     else if (gOutline->contourCount == -1)
  303.     {    short flags, index, newMatrix;
  304.  
  305.         gOutline->contourCount = gOutline->pointCount = 0;
  306.         SHS(gOutline->endPoints, 0);
  307.         SHS(gOutline->onCurve, 0);
  308.         SHS(gOutline->x, 0);
  309.         SHS(gOutline->y, 0);
  310.         do
  311.         {    Matrix compXform;
  312.             short arg1, arg2;
  313.             
  314.             flags = *glyph++;
  315.             index = *glyph++;
  316.             newMatrix = false;
  317.  
  318.             if ( flags & ARG_1_AND_2_ARE_WORDS )
  319.             {    arg1 = *glyph++;
  320.                 arg2 = *glyph++;
  321.             }
  322.             else
  323.             {    char* byteP = (char*)glyph;
  324.                 if ( flags & ARGS_ARE_XY_VALUES )
  325.                 {    /* offsets are signed */
  326.                     arg1 = *byteP++;
  327.                     arg2 = *byteP;
  328.                 }
  329.                 else
  330.                 {    /* anchor points are unsigned */
  331.                     arg1 = (unsigned char)*byteP++;
  332.                     arg2 = (unsigned char)*byteP;
  333.                 }
  334.                 ++glyph;
  335.             }
  336. #if IMPLEMENT_SCALED_COMPONENTS
  337.             if ( flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO) )
  338.             {    Matrix subXform;
  339.                 MakeIdentityMatrix(subXform);
  340.                 if ( flags & WE_HAVE_A_TWO_BY_TWO )
  341.                 {    compXform[0][0] = (Fixed)*glyph++ << 2;
  342.                     compXform[0][1] = (Fixed)*glyph++ << 2;
  343.                     compXform[1][0] = (Fixed)*glyph++ << 2;
  344.                     compXform[1][1] = (Fixed)*glyph++ << 2;
  345.                 }
  346.                 else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE )
  347.                 {    compXform[0][0] = (Fixed)*glyph++ << 2;
  348.                     compXform[1][1] = (Fixed)*glyph++ << 2;
  349.                 }
  350.                 else
  351.                     compXform[0][0] = compXform[1][1] = (Fixed)*glyph++ << 2;
  352.                 PostMulMatrix(compXform, xform);
  353.                 newMatrix = true;
  354.             }
  355. #endif            
  356.             {    GlyphOutline out;
  357.                 InitGlyphOutline(&out);
  358.                 GetGlyphOutline(sfnt, index, &out, newMatrix ? compXform : xform);
  359.                 {    Fixed dx, dy;
  360.                     if (flags & ARGS_ARE_XY_VALUES)
  361.                     {    dx = FixRatio(arg1, upem);
  362.                         dy = -FixRatio(arg2, upem);
  363.                     }
  364.                     else
  365.                     {    dx = (*gOutline->x)[arg1] - (*out.x)[arg2];
  366.                         dy = (*gOutline->y)[arg1] - (*out.y)[arg2];
  367.                     }
  368.                     MoveGlyphOutline(&out, dx, dy);
  369.                 }
  370.                 AppendGlyphOutline(gOutline, &out);
  371.                 KillGlyphOutline(&out);
  372.             }
  373.         } while (flags & MORE_COMPONENTS);
  374.     }
  375.     else if (gOutline->contourCount > 0)
  376.     {    /*    Load in the end points.
  377.          */
  378.         {    long size = gOutline->contourCount * sizeof(short);
  379.  
  380.             if (SHS(gOutline->endPoints, size))
  381.             {    error = fMemoryError;
  382.                 goto EXIT;
  383.             }
  384.             BlockMove( (Ptr)glyph, (Ptr)*gOutline->endPoints, size );
  385.             glyph += gOutline->contourCount;
  386.         }
  387.  
  388.         gOutline->pointCount = (*gOutline->endPoints)[gOutline->contourCount - 1] + 1;
  389.         if (SHS(gOutline->onCurve, gOutline->pointCount * sizeof(char)))
  390.         {    error = fMemoryError;
  391.             goto EXIT;
  392.         }
  393.         if (SHS(gOutline->x, gOutline->pointCount * sizeof(Fixed)))
  394.         {    error = fMemoryError;
  395.             goto EXIT;
  396.         }
  397.         if (SHS(gOutline->y, gOutline->pointCount * sizeof(Fixed)))
  398.         {    error = fMemoryError;
  399.             goto EXIT;
  400.         }
  401.  
  402.         /*    Skip the word for instruction count + the instructions.
  403.          *    Then load in the onCurve bytes.
  404.          */
  405.         {    Byte* p = (Byte*)glyph + sizeof(short) + *glyph;
  406.             Byte* onCurve = *gOutline->onCurve;
  407.             Byte* stop = onCurve + gOutline->pointCount;
  408.             Byte flag;
  409.  
  410.             while (onCurve < stop)
  411.             {    *onCurve++ = flag = GetUnsignedByte( p );
  412.                 if ( flag & REPEAT_FLAGS ) {
  413.                     short count = GetUnsignedByte( p );
  414.                     for (--count; count >= 0; --count)
  415.                         *onCurve++ = flag;
  416.                 }
  417.             }
  418.             /*    Lets do X
  419.             */
  420.             {    short coord = adjustToLsb;
  421.                 Fixed* x = *gOutline->x;
  422.  
  423.                 onCurve = *gOutline->onCurve;
  424.                 while (onCurve < stop)
  425.                 {    if ( (flag = *onCurve++) & XSHORT ) {
  426.                         if ( flag & SHORT_X_IS_POS )
  427.                             coord += GetUnsignedByte( p );
  428.                         else
  429.                             coord -= GetUnsignedByte( p );
  430.                     }
  431.                     else if ( !(flag & NEXT_X_IS_ZERO) )
  432.                     {    coord += (short)(*p++) << 8;
  433.                         coord += (Byte)*p++;
  434.                     }
  435.                     *x++ = FixRatio( coord, upem );
  436.                 }
  437.             }
  438.             /*    Lets do Y
  439.             */
  440.             {    short coord = 0;
  441.                 Fixed* y = *gOutline->y;
  442.  
  443.                 onCurve = *gOutline->onCurve;
  444.                 while (onCurve < stop)
  445.                 {    if ( (flag = *onCurve) & YSHORT ) {
  446.                         if ( flag & SHORT_Y_IS_POS )
  447.                             coord += GetUnsignedByte( p );
  448.                         else
  449.                             coord -= GetUnsignedByte( p );
  450.                     }
  451.                     else if ( !(flag & NEXT_Y_IS_ZERO) )
  452.                     {    coord += (short)(*p++) << 8;
  453.                         coord += (Byte)*p++;
  454.                     }
  455.                     *y++ = -FixRatio( coord, upem );
  456.                     
  457.                     /*    Filter off the extra bits
  458.                     */
  459.                     *onCurve++ = flag & ONCURVE;
  460.                 }
  461.             }
  462.         }
  463.     }
  464.     else
  465.         error = fUnimplemented;
  466. EXIT:
  467.     SetFontState( sfnt, state );
  468.  
  469.     return PostFontError(error);
  470. }
  471.  
  472.